<?php
namespace app\admin\controller;
use app\service\invoiceService;
use think\Controller;
use app\admin\controller\Common;
use app\service\billService;
use app\service\commonService;
use app\service\roominfoService;
use app\service\apiService;
use think\Db;
use printing\printDemo;
use invoice\Api as InvoiceApi;
use think\Log;

class Invoice extends Common{


    public function getToken($serviceinfo){
        if($serviceinfo["fp_version"]=="v2"){
            //判断access_token是否到期
            $second = strtotime(date('Y-m-d H:i:s',time()))-strtotime($serviceinfo['fp_expires_in_v2']);
            if($second <86400){
                //未过期
                $access_token = $serviceinfo['fp_access_token_v2'];
            }else{
                //过期从新获取
                $access_token = $this->accessTokenV2($serviceinfo['fp_app_key_v2'],$serviceinfo['fp_app_secret_v2']);
            }
        }else{
            //判断access_token是否到期
            $second = strtotime(date('Y-m-d H:i:s',time()))-strtotime($serviceinfo['fp_expires_in']);
            if($second <86400){
                //未过期
                $access_token = $serviceinfo['fp_access_token'];
            }else{
                //过期从新获取
                $access_token = $this->accessToken($serviceinfo['fp_app_key'],$serviceinfo['fp_app_secret']);
            }
        }

        return $access_token;
    }

   
    //开票接口
    public function invoice(){
        //查询是否有access_token
        //判断是否存在该数据
        $id = explode(',',request()->param('id'));

        $billinfo = (new billService())->billEntryIdInfo($id);
        if (count($billinfo) != count($id)) {
            return json(['error' => '账单信息不完整']);
        }
        //判断房号是否相同
        foreach($billinfo as $inf){
            if($inf['status'] !== 'TRADE_SUCCESS'){
                return json(['error' => '账单未付款,不能开发票']);
            }
            if($inf['invoice_type'] == '1'){
                return json(['error' => '不能重复开票']);
            }
            //die;
            $out_room_id[] = $inf['out_room_id'];
            $bill_entry_amount=$inf['bill_entry_amount'];
            //根据费用类型查询税率
            $taxrate = (new billService())->taxRateCommunity($inf['cost_type'],$inf['community_id']);
            if(empty($taxrate)){
            	return "请添加该小区的费用类型";
            }
            $goodsCode = (new billService())->goodsCodeCommunity($inf['cost_type'],$inf['community_id']);
            //var_dump($goodsCode);die;
            $tax = $inf['bill_entry_amount']*$taxrate;
            if(!empty($inf["discount_money"])){
                $discount_money_arr=explode("(",$inf["discount_money"]);
                $bill_entry_amount=$discount_money_arr[0];
                $tax=$discount_money_arr[0]*$taxrate;
            }

            if(($inf['cost_type']=="预交2020年物业费95折2020年1月31日截止")||($inf['cost_type']=="预交2020年物业费9折2020年1月31日截止")||$inf['cost_type']=="预交2020年物业费98折2020年2月29日截止"||($inf['cost_type']=="预交2019年物业费95折2018年12月31日截止")){
                $inf['cost_type']="物业费";
            }
            $costTypeInfo=(new billService())->getCostTypeInfo($inf['cost_type'],$inf['community_id']);
            //$inf['cost_type']="物业费";
            $invoiceDetail[] = "{\"goodsName\":\"{$inf['cost_type']}\",\"specType\":\"{$inf['acct_period']}\",\"unit\":\"期\",\"num\":\"1\",\"price\":\"{$bill_entry_amount}\",\"withTaxFlag\":\"1\",\"taxRate\":\"{$taxrate}\",\"tax\":\"{$tax}\",\"goodsCode\":\"{$goodsCode}\",\"favouredPolicyFlag\":\"{$costTypeInfo['favouredPolicyFlag']}\"}";
            $remark[] = $inf['pay_type'].'支付';
        }
        
        $out_room_id = array_unique($out_room_id);
        if(count($out_room_id) !== 1){
            return json(['error' => '账单信息不是一户']);            
        }
        $invoiceDetail = implode(',', $invoiceDetail);
        $remark = implode(',', $remark);
        //根据房屋号查询业主信息
        // dump($billinfo);
        $roominfo = (new roominfoService())->roomEntryIdInfo($out_room_id);
        if(empty($roominfo)){
            return json(['error' => '房屋信息错误']);            
        }
        // dump($roominfo);
        $communityinfo = (new billService())->communityName($roominfo[0]['community_id']);
        // dump($communityinfo);
        $propertyinfo = (new billService())->propertyInfo($communityinfo['property_id']);
        $serviceinfo = (new billService())->serviceInfo($propertyinfo['service_id']);
        //dump($serviceinfo);exit;

        $invoiceConfig=(new invoiceService())->getInvoiceConfig($serviceinfo);
        if($invoiceConfig["errCode"]!='0'){
            return $invoiceConfig["errMsg"];
        }
        //var_dump($invoiceConfig);exit;
//        if(empty($serviceinfo["fp_app_key"])){
//            return "请先配置发票信息";
//        }
       // $access_token =$this->getToken($serviceinfo);
        //$appKey = $serviceinfo["fp_app_key"];
     	//$appSecret = $serviceinfo["fp_app_secret"];

        $appKey = $invoiceConfig["appKey"];
        $appSecret = $invoiceConfig["appSecret"];
    	$token = $invoiceConfig["token"];// please store the token and refresh it before expired

    	$taxnum = $serviceinfo["fp_saler_tax_num"];
        
    	$url = "https://sdk.nuonuo.com/open/v1/services"; // change to online domain
    	$method = $invoiceConfig["method"];// change to your method
//        if($serviceinfo["fp_version"]=='v2'){
//            $appKey = $serviceinfo["fp_app_key_v2"];
//            $appSecret = $serviceinfo["fp_app_secret_v2"];
//            $method="nuonuo.OpeMplatform.requestBillingNew";
//        }

		$senid = uniqid(); // generate your meaningful senid
		
		$invoiceDate = date('Y-m-d H:i:s',time());
        $orderNo = time().rand(100000,999999);
        $timestmp = time(); 
        $buyerName=$communityinfo['community_name'].$roominfo[0]['address'].$roominfo[0]['owner_name'];
        $buyerPhone=$roominfo[0]["owner_phone"];
        //$buyerPhone="188561510";
        $fp_saler_tax_num=$serviceinfo['fp_saler_tax_num'];
        $salerAddress=$serviceinfo['address'];
        $salerTel=$serviceinfo['phone'];
        $salerAddress=$serviceinfo['address'];
        $salerAccount=$serviceinfo['fp_saler_account'];
        $emt="";

        //var_dump($content);"invoiceLine": "pc",
        $body = "{
        \"order\": {
            \"buyerName\": \"$buyerName\",
            \"orderNo\": \"$orderNo\",
            \"invoiceDate\": \"$invoiceDate\",
            \"clerk\": \"\",
            \"salerTaxNum\": \"$fp_saler_tax_num\",
            \"salerTel\": \"$salerTel\",
            \"salerAddress\": \"$salerAddress\",
            \"salerAccount\": \"$salerAccount\",
            \"invoiceType\": \"1\",
            \"invoiceLine\": \"pc\",
            \"pushMode\": \"1\",
            \"buyerPhone\": \"$buyerPhone\",
            \"remark\": \"$remark\",
            \"invoiceDetail\": [$invoiceDetail],
            \"callBackUrl\": \"http://www.wuye.zfbzhsq.com/admin/invoice/callback\"
            }
        }";
        
        //var_dump($body);die;
       

        $result = InvoiceApi::sendPostSyncRequest($url, $senid, $appKey, $appSecret, $token, $taxnum, $method, $body);
        //echo "<pre>"; var_dump($result);exit;
		$result = json_decode($result, true);
        //Log::write($result,"PDF发票");
        if($result['code'] == 'E0000'){
            $invoiceSerialNum = $result['result']['invoiceSerialNum'];
            foreach($billinfo as $inf){
                $data['id'] = $inf['id'];
                $data['invoice_serial_num'] = $invoiceSerialNum;
                $data['invoice_type'] = 1;
                $data['invoiceTime'] = time();
                $data['fp_version'] =$serviceinfo["fp_version"];
                $billinvoiceSerialNum = (new billService())->billApiEdit($data);
            }
        }else{
            return json(['error' => $result['describe']]);
        }
        $this->success("付款成功");
        //return json(['success' => '开票成功']);
    }
    
    //发票冲红
    public function Cancellation(){
        //判断是否存在该数据
        $id = explode(',',request()->param('id')); 
        //var_dump($id);die; 
        $billidinfo = (new billService())->billEntryIdInfo($id);
        if(empty($billidinfo)){
            return '账单信息错误';
        }
        //根据发票号查询开票账单
        $billinfo = (new billService())->numBillInfo($billidinfo[0]['invoice_serial_num']);
        if(empty($billinfo)){
            return json(['error' => '已冲红或未开票']);            
        }
        //判断房号是否相同
        foreach($billinfo as $inf){
            if($inf['status'] !== 'TRADE_SUCCESS'){
                return json(['error' => '账单未付款,不能开发票']);
            }
            $out_room_id[] = $inf['out_room_id'];
            //根据费用类型查询税率
            $taxrate = (new billService())->taxRateCommunity($inf['cost_type'],$inf['community_id']);
            //$taxrate = (new billService())->taxRate($inf['cost_type']);
            $tax = $inf['bill_entry_amount']*$taxrate;
            $invoiceDetail[] = "{'goodsName':'{$inf['cost_type']}','specType':'{$inf['acct_period']}','unit':'期','num':'-1','price':'{$inf['bill_entry_amount']}','withTaxFlag':'1','taxRate':'{$taxrate}','tax':'-{$tax}'}";
            $remark[] = $inf['pay_type'].'支付';
        }
        $out_room_id = array_unique($out_room_id);
        if(count($out_room_id) !== 1){
            return json(['error' => '账单信息不是一户']);            
        }
        $invoiceDetail = implode(',', $invoiceDetail);
        $remark = implode(',', $remark);
        //根据房屋号查询业主信息
        $roominfo = (new roominfoService())->roomEntryIdInfo($out_room_id);
        if(empty($roominfo)){
            return json(['error' => '房屋信息错误']);            
        }
        $communityinfo = (new billService())->communityName($roominfo[0]['community_id']);
        $propertyinfo = (new billService())->propertyInfo($communityinfo['property_id']);
        $serviceinfo = (new billService())->serviceInfo($propertyinfo['service_id']);
        //判断access_token是否到期
        $second = strtotime(date('Y-m-d H:i:s',time()))-strtotime($serviceinfo['fp_expires_in']);
        if($second < 86400){
            //未过期
            $access_token = $serviceinfo['fp_access_token'];
        }else{
            //过期从新获取
            $access_token = $this->accessToken($serviceinfo['fp_app_key'],$serviceinfo['fp_app_secret']);
        }
        $invoiceDate = date('Y-m-d H:i:s',time());
        $orderNo = time().rand(100000,999999);
        $timestmp = time();
        
        
        $appKey = $serviceinfo["fp_app_key"];
     	$appSecret = $serviceinfo["fp_app_secret"];
    	$token = $access_token;// please store the token and refresh it before expired
    	$taxnum = $serviceinfo["fp_saler_tax_num"];
        $url = "https://sdk.nuonuo.com/open/v1/services"; // change to online domain
        
        $method2 = "nuonuo.electronInvoice.CheckEInvoice"; // change to your method
		$senid2 = uniqid(); // generate your meaningful senid
		$body2 = json_encode(
			array(
				"invoiceSerialNum" => array($billinfo[0]['invoice_serial_num'])
			)
		);
        
		$result2 = InvoiceApi::sendPostSyncRequest($url, $senid2, $appKey, $appSecret, $token, $taxnum, $method2, $body2);
        $result2 = json_decode($result2, true);
        if($result2['code'] != 'E0000'){
           return json(['error' => $result2['describe']]);
        }
        //var_dump($result2);die;
        $invoiceCode = $result2['result'][0]['invoiceCode'];
        $invoiceNum = $result2['result'][0]['invoiceNum'];
        
    	
    	$method = "nuonuo.electronInvoice.requestBilling"; // change to your method
		$senid = uniqid(); // generate your meaningful senid
		
		$invoiceDate = date('Y-m-d H:i:s',time());
        $orderNo = time().rand(100000,999999);
        $timestmp = time(); 
        $buyerName=$communityinfo['community_name'].$roominfo[0]['address'].$roominfo[0]['owner_name'];
        $buyerPhone=$roominfo[0]["owner_phone"];
        //$buyerPhone="188561510";
        $fp_saler_tax_num=$serviceinfo['fp_saler_tax_num'];
        $salerAddress=$serviceinfo['address'];
        $salerTel=$serviceinfo['phone'];
        $salerAddress=$serviceinfo['address'];
        $salerAccount=$serviceinfo['fp_saler_account'];
        $body = "{
        \"order\": {
            \"buyerName\": \"$buyerName\",
            \"orderNo\": \"$orderNo\",
            \"invoiceDate\": \"$invoiceDate\",
            \"clerk\": \"\",
            \"salerTaxNum\": \"$fp_saler_tax_num\",
            \"salerTel\": \"$salerTel\",
            \"salerAddress\": \"$salerAddress\",
            \"salerAccount\": \"$salerAccount\",
            \"invoiceType\": \"2\",
            \"invoiceCode\": \"$invoiceCode\",
            \"invoiceNum\": \"$invoiceNum\",
            \"pushMode\": \"1\",
            \"buyerPhone\": \"$buyerPhone\",
            \"invoiceDetail\": [$invoiceDetail],
            \"callBackUrl\": \"http://www.jfzhiwen.com/admin/invoice/callback/\"
            }
        }";
       
           
        
        $result = InvoiceApi::sendPostSyncRequest($url, $senid, $appKey, $appSecret, $token, $taxnum, $method, $body);
        //var_dump($result);
		
        $result = json_decode($result, true);
        if($result['code'] == 'E0000'){
            $invoiceSerialNum = $result['result']['invoiceSerialNum'];
            foreach($billinfo as $inf){
                $data['id'] = $inf['id'];
                $data['invoice_serial_num'] = $invoiceSerialNum;
                $data['invoice_type'] = 2;
                $billinvoiceSerialNum = (new billService())->billApiEdit($data);
                return json(['info' => '开票成功']);       
            }
        }else{
            return json(['error' => $result['describe']]);
        }
        
    }
    
    public function CheckEInvoice() 
	{
	    $id = request()->param('id');


        $billinfo = (new billService())->billIdinfo($id);
        if(!empty($billinfo["invoiceFileUrl"])){
            return $this->redirect($billinfo['invoiceFileUrl']);
        }
        //判断房号是否相同
        $communityinfo = (new billService())->communityName($billinfo['community_id']);
        
        $propertyinfo = (new billService())->propertyInfo($communityinfo['property_id']);
        
        $serviceinfo = (new billService())->serviceInfo($propertyinfo['service_id']);
        //echo "<pre>";var_dump($serviceinfo);die;
        $invoiceConfig=(new invoiceService())->getInvoiceConfig($serviceinfo);
        if($invoiceConfig["errCode"]!='0'){
            return $invoiceConfig["errMsg"];
        }

        $appKey = $invoiceConfig["appKey"];
        $appSecret = $invoiceConfig["appSecret"];
        $token = $invoiceConfig["token"];// please store the token and refresh it before expired

        $taxnum = $serviceinfo["fp_saler_tax_num"];

        $url = "https://sdk.nuonuo.com/open/v1/services";

        $timestmp = time();// change to online domain
        $method = $invoiceConfig["queryInvoiceMethod"];

		$senid = uniqid(); // generate your meaningful senid

		$body = json_encode(
			array(
				"invoiceSerialNum" => array($billinfo['invoice_serial_num'])
			)
		);
        if($serviceinfo["fp_version"]=="v2"){
            $body = json_encode(
                array(
                    "serialNos" => array($billinfo['invoice_serial_num'])
                )
            );
        }

		$result = InvoiceApi::sendPostSyncRequest($url, $senid, $appKey, $appSecret, $token, $taxnum, $method, $body);
	
	
		$result = json_decode($result, true);
			//
        //echo "<pre>";var_dump($result);die;

        if($result['code'] == 'E0000'){
            if(!$result["result"][0]['invoiceNo']){
                return $result["result"][0]["resultMsg"];
            }
            $info["invoiceCode"]=$result["result"][0]['invoiceCode'];
            $info["invoiceNum"]=$result["result"][0]['invoiceNo'];
            $info["invoiceFileUrl"]=$result["result"][0]['pdfUrl'];//pdfUrl
            Db::table("bill")->where("id",$id)->update($info);
            return $this->redirect($info["invoiceFileUrl"]);
        }else{
            return json(['error' => $result['describe']]);
        }
		return $res;
	}
	
	public function delivery(){
	    if(request()->isPost()){
	        $data=request()->post();
	        $billinfo = (new billService())->billIdinfo($data["id"]);
	        
            $communityinfo = (new billService())->communityName($billinfo['community_id']);
            $propertyinfo = (new billService())->propertyInfo($communityinfo['property_id']);
            $serviceinfo = (new billService())->serviceInfo($propertyinfo['service_id']);
            //判断access_token是否到期
            $second = strtotime(date('Y-m-d H:i:s',time()))-strtotime($serviceinfo['fp_expires_in']);
            if($second < 86400){
                //未过期
                $access_token = $serviceinfo['fp_access_token'];
            }else{
                //过期从新获取
                $access_token = $this->accessToken($serviceinfo['fp_app_key'],$serviceinfo['fp_app_secret']);
                //return $access_token;
            }
	        $phone=$data["phone"];
	        $mail=$data["mail"];
	        $url = "https://sdk.nuonuo.com/open/v1/services"; 
    	    $method = "nuonuo.ElectronInvoice.deliveryInvoice";
    	    
	        $appKey = $serviceinfo["fp_app_key"];
     	    $appSecret = $serviceinfo["fp_app_secret"];
    	    $token = $access_token;// please store the token and refresh it before expired
    	    $taxnum = $serviceinfo["fp_saler_tax_num"];
            
            $senid = uniqid(); //唯一标识，由企业自己生成32位随机码
            $body = '{"invoiceSerialNum":["your.voicecode"]}';//API私有请求参数
            $invoiceCode=$billinfo["invoiceCode"];
            $invoiceNum=$billinfo["invoiceNum"];
            $body="{
                  \"mail\": \"$mail\",
                  \"phone\": \"$phone\",
                  \"taxnum\": \"$taxnum\",
                  \"invoiceCode\": \"$invoiceCode\",
                  \"invoiceNum\": \"$invoiceNum\"
                }";
            $res = InvoiceApi::sendPostSyncRequest($url, $senid, $appKey, $appSecret, $token, $taxnum, $method, $body);
            $result = json_decode($res, true);
		
            if($result['code'] == 'E0000'){
                $msg["mail"]=$mail;
                $msg["phone"]=$phone;
                $msg["taxnum"]=$taxnum;
                $msg["invoiceCode"]=$invoiceCode;
                $msg["invoiceNum"]=$invoiceNum;
                $msg["create_time"]=time();
                Db::table("invoice_msg_log")->insert($msg);
               return "信息推送成功";
            }else{
                return json(['error' => $result['describe']]);
            }
	    }else{
	        $id=request()->get("id");
	        
            $billinfo = (new billService())->billIdinfo($id);
            $this->assign("info",$billinfo);
            return $this->fetch();
	    }
	    
	}
    
    //当access_token超时时，获取access_token
    public function accessToken($client_id,$client_secret){
        $res = InvoiceApi::getMerchantToken($client_id, $client_secret);
		$tmpInfo = json_decode($res);

        
        if(property_exists($tmpInfo,'error')){
            //var_dump($tmpInfo);die;
            //return $tmpInfo;
            $this->error($tmpInfo->error.',access_token获取失败');
        }
        $data['fp_access_token'] = $tmpInfo->access_token;//获取access_token
        $data['fp_expires_in'] = date('Y-m-d H:i:s',time());
        $data['id'] = (new billService())->serviceFpAppKey($client_id);
        // 存储access_token
        $result = (new billService())->serviceUpdate($data);
        return $data['fp_access_token'];
        // $tmpInfo = '{"access_token":"10ffd45208fb4464aa6fee00vthjozss","expires_in":86400}';
        
    }

    public function accessTokenV2($client_id,$client_secret){
        $res = InvoiceApi::getMerchantToken($client_id, $client_secret);
        $tmpInfo = json_decode($res);
        if(property_exists($tmpInfo,'error')){
            //var_dump($tmpInfo);die;
            //return $tmpInfo;
            $this->error($tmpInfo->error.',access_token获取失败');
        }
        $data['fp_access_token_v2'] = $tmpInfo->access_token;//获取access_token
        $data['fp_expires_in_v2'] = date('Y-m-d H:i:s',time());
        $data['id'] = (new billService())->serviceFpAppKeyV2($client_id);
        // 存储access_token
        $result = (new billService())->serviceUpdate($data);
        return $data['fp_access_token_v2'];
        // $tmpInfo = '{"access_token":"10ffd45208fb4464aa6fee00vthjozss","expires_in":86400}';

    }
	public function getMerchantToken() {
		$appKey = "your.appKey";
		$appSecret = "your.appSecret";
		$res = InvoiceApi::getMerchantToken($appKey, $appSecret);
		return $res;
	}

	public function getISVToken() {
		$appKey = "your.appKey";
		$appSecret = "your.appSecret";
		$code = "your.code";
		$taxnum = "your.merchant.taxnum";
		$redirectUri = "your.redirectUri";
		$res = InvoiceApi::getISVToken($appKey, $appSecret, $code, $taxnum, $redirectUri);
		return $res;
	}

	public function refreshISVToken() {
		$refreshToken = "your.token";
		$appSecret = "your.appSecret";
		$userId = "your.userId";
		$res = InvoiceApi::refreshISVToken($refreshToken, $userId, $appSecret);
		return $res;
	}
	
	public function test(){
	    $appKey = "uXig5unv";
		$appSecret = "B69D206D6E564A6E";
		$code = request()->get("code");
		$taxnum = "91330110352478198K";
		$redirectUri = "https://www.wuye.zfbzhsq.com/admin/invoice/test";
		$res = InvoiceApi::getISVToken($appKey, $appSecret, $code, $taxnum, $redirectUri);
		var_dump($res);
		return $res;
	}

	public function callback(){
        $path=dir(getcwd())->path.'/invoice/'.date('Ymd');
        if (! file_exists ( $path )) {
            mkdir ( "$path", 0777, true );
        }
        $address = $path."/".date('His').rand(100000,999999).'.txt';
        file_put_contents($address,file_get_contents("php://input"),FILE_APPEND);//将数据读入文本

    }
}